/******************************************************************************
*    Copyright (C), 2022 by D2X studio. All rights reserved.                  *
*                                                                             *
*    @file:      uart.c
*    @owner:     zhengjian.xie@gmail.com                                      *
*    @desc:                                                                   *
*    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +    *
* history:                                                                    *
*  <author>      <time>      <version>              <description>             *
*  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  *
*  |  Xzj |  20220423[14:39] | 1.0.0 |                  build              |  *
*  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -  *
******************************************************************************/
#include "includes.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <termios.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>

void onUART_command(unsigned char* data, unsigned char length) {

}
/** terminal data define */
static stEvent __uart_evt__ = { -1, no, nil };

void uart_callback(void) {
    int ret, i;
    unsigned char buf[128] = { 0 };

    static unsigned char cmdBytes = 0;
    static unsigned char cmd[256] = { 0 };

    ret = read(__uart_evt__.fd, buf, sizeof(buf));
    if ( ret > 0 ) {
        for ( i = 0; i < ret; i++ ) {
            if ( (0 == cmdBytes) && (0xCC == buf[i]) || (0xCC == cmd[0]) ) {
                cmd[cmdBytes++] = buf[i];
            }
            if ( !(cmdBytes >= 2 && 0x66 == buf[1]) ) {
                cmd[cmdBytes = 0] = 0;
            }
            if ( cmdBytes >= 6 ) {
                if ( 1 ) { // CRC OK
                    onUART_command(cmd, cmdBytes);
                    cmd[cmdBytes = 0] = 0;
                }
            }
            if ( cmdBytes >= 256 ) { // prevent ERR
                cmd[cmdBytes = 0] = 0;
            }
        }
    }
}

/** terminal_init */
void uart_init(void) {
    int fd;
    struct termios opt;

    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY);
    if ( fd <= 0 ) {
        printf("UART: open error: %d\n", errno);
        return ;
    }

    tcgetattr(fd, &opt);
    cfsetispeed(&opt, B115200);
    cfsetospeed(&opt, B115200);
    opt.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
    opt.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
    opt.c_oflag &= ~(OPOST);
    opt.c_cflag &= ~(CSIZE | PARENB);
    opt.c_cflag |= CS8;
    opt.c_cc[VTIME] = 100;
    opt.c_cc[VMIN] = 1;
    tcflush(fd, TCIFLUSH);

    if ( tcsetattr(fd, TCSANOW, &opt) ) {
        printf("UART: tcsetattr error: %d\n", errno);
        close(fd);
    }

    __uart_evt__.fd = fd;
    __uart_evt__.doEvent = uart_callback;
    app_event_add(&__uart_evt__);
}

/** uart_deinit */
void uart_deinit(void) {
    app_event_del(&__uart_evt__);
}

/** uart send str */
void uart_sendstr(const char* str) {
    if ( __uart_evt__.fd > 0 ) {
        write(__uart_evt__.fd, str, strlen(str) + 1);
    }
}
